More improvements
authorRaph Levien <raph@google.com>
Thu, 26 Jan 2017 17:09:07 +0000 (09:09 -0800)
committerRaph Levien <raph@google.com>
Thu, 26 Jan 2017 20:47:50 +0000 (12:47 -0800)
Use Context::target_filenames rather than trying to redo that.

Traverse path dependencies recursively, so we get transitive deps.

Use existing fingerprint parsing.

src/cargo/ops/cargo_rustc/fingerprint.rs
src/cargo/ops/cargo_rustc/output_depinfo.rs

index 02ea5a47f620c31b61484434ab5a500ad5b07eb9..d892a65172129c9e23ddcb1a952f255208d22cfc 100644 (file)
@@ -563,7 +563,8 @@ fn log_compare(unit: &Unit, compare: &CargoResult<()>) {
     }
 }
 
-fn dep_info_mtime_if_fresh(dep_info: &Path) -> CargoResult<Option<FileTime>> {
+// Parse the dep-info into a list of paths
+pub fn parse_dep_info(dep_info: &Path) -> CargoResult<Option<Vec<PathBuf>>> {
     macro_rules! fs_try {
         ($e:expr) => (match $e { Ok(e) => e, Err(..) => return Ok(None) })
     }
@@ -600,8 +601,15 @@ fn dep_info_mtime_if_fresh(dep_info: &Path) -> CargoResult<Option<FileTime>> {
         }
         paths.push(cwd.join(&file));
     }
+    Ok(Some(paths))
+}
 
-    Ok(mtime_if_fresh(&dep_info, paths.iter()))
+fn dep_info_mtime_if_fresh(dep_info: &Path) -> CargoResult<Option<FileTime>> {
+    if let Some(paths) = parse_dep_info(dep_info)? {
+        Ok(mtime_if_fresh(&dep_info, paths.iter()))
+    } else {
+        Ok(None)
+    }
 }
 
 fn pkg_fingerprint(cx: &Context, pkg: &Package) -> CargoResult<String> {
index 7c8ac327609e31a9d34c0cfa49d8c555126eb593..add28e023e31adf0a84575c9e446bc1c53b61251 100644 (file)
@@ -1,23 +1,11 @@
-use std::borrow::ToOwned;
 use std::collections::HashSet;
-use std::io::{Read, Write};
+use std::io::Write;
 use std::fs::File;
 use std::path::{Path, PathBuf};
 
-use core::{TargetKind};
 use ops::{Context, Unit};
-use util::{CargoResult, internal, human};
-
-#[derive(Debug)]
-struct DepLine {
-    target: String,
-    deps: Vec<String>,
-}
-
-struct DepFile {
-    dir: String,
-    deps: Vec<DepLine>,
-}
+use util::{CargoResult, internal};
+use ops::cargo_rustc::fingerprint;
 
 fn render_filename<P: AsRef<Path>>(path: P, basedir: Option<&str>) -> CargoResult<String> {
     let path = path.as_ref();
@@ -28,101 +16,50 @@ fn render_filename<P: AsRef<Path>>(path: P, basedir: Option<&str>) -> CargoResul
             _ => path,
         }
     };
-    relpath.to_str().ok_or(internal("path not utf-8")).map(ToOwned::to_owned)
+    relpath.to_str().ok_or(internal("path not utf-8")).map(|f| f.replace(" ", "\\ "))
 }
 
-fn read_dep_file<P: AsRef<Path>>(path: P) -> CargoResult<DepFile> {
-    let mut file = File::open(&path).map_err(|_|
-        human("error opening ".to_string() + path.as_ref().to_str().unwrap_or("(bad unicode")))?;
-    let mut contents = String::new();
-    let _ = file.read_to_string(&mut contents)?;
-    let mut spl = contents.split('\0');
-    let dir = spl.next().ok_or(internal("dependency file empty"))?;
-    let dep_txt = spl.next().ok_or(internal("dependency file missing null byte"))?;
-    let mut result = Vec::new();
-    for line in dep_txt.lines() {
-        let mut line_spl = line.split(": ");
-        if let Some(target) = line_spl.next() {
-            if let Some(deps) = line_spl.next() {
-                let deps = deps.split_whitespace().map(ToOwned::to_owned).collect();
-                result.push(DepLine {
-                    target: target.to_string(),
-                    deps: deps,
-                });
-            }
-        }
+fn add_deps_for_unit<'a, 'b>(deps: &mut HashSet<PathBuf>, context: &mut Context<'a, 'b>,
+    unit: &Unit<'a>, visited: &mut HashSet<Unit<'a>>) -> CargoResult<()>
+{
+    if visited.contains(unit) {
+        return Ok(());
     }
-    Ok(DepFile {
-        dir: dir.to_string(),
-        deps: result,
-    })
-}
+    visited.insert(unit.clone());
 
-fn add_deps(depfile: &DepFile, deps: &mut HashSet<PathBuf>) {
-    let dep_dir = PathBuf::from(&depfile.dir);
-    for depline in &depfile.deps {
-        for dep in &depline.deps {
-            deps.insert(dep_dir.join(dep));
+    let dep_info_loc = fingerprint::dep_info_loc(context, unit);
+    if let Some(paths) = fingerprint::parse_dep_info(&dep_info_loc)? {
+        for path in paths {
+            deps.insert(path);
         }
     }
-}
-
-// TODO: probably better to use Context::target_filenames for this
-fn target_filename(context: &mut Context, unit: &Unit) -> CargoResult<PathBuf> {
-    let (dir, base) = context.link_stem(&unit).ok_or(internal("can't get link stem"))?;
-    if unit.target.is_lib() {
-        Ok(dir.join(["lib", &base, ".rlib"].concat()))
-    } else {
-        Ok(dir.join(base))
-    }
-}
 
-fn add_deps_for_unit(deps: &mut HashSet<PathBuf>, context: &mut Context, unit: &Unit)
-    -> CargoResult<()>
-{
-    // TODO: this is duplicated against filename in fingerprint.rs
-    let kind = match *unit.target.kind() {
-        TargetKind::Lib(..) => "lib",
-        TargetKind::Bin => "bin",
-        TargetKind::Test => "integration-test",
-        TargetKind::ExampleBin |
-        TargetKind::ExampleLib(..) => "example",
-        TargetKind::Bench => "bench",
-        TargetKind::CustomBuild => "build-script",
-    };
-    let flavor = if unit.profile.test {
-        "test-"
-    } else if unit.profile.doc {
-        "doc-"
-    } else {
-        ""
-    };
-    let dep_filename = ["dep-", flavor, kind, "-", &context.file_stem(&unit)].concat();
-    let path = context.fingerprint_dir(&unit).join(&dep_filename);
-    let depfile = read_dep_file(&path)?;
-    add_deps(&depfile, deps);
-    Ok(())
-}
-
-pub fn output_depinfo(context: &mut Context, unit: &Unit) -> CargoResult<()> {
-    let mut deps = HashSet::new();
-    add_deps_for_unit(&mut deps, context, unit)?;
+    // recursively traverse all transitive dependencies
     for dep_unit in &context.dep_targets(unit)? {
         let source_id = dep_unit.pkg.package_id().source_id();
         if source_id.is_path() {
-            add_deps_for_unit(&mut deps, context, dep_unit)?;
+            add_deps_for_unit(deps, context, dep_unit, visited)?;
         }
     }
-    let filename = target_filename(context, unit)?;
-    let mut output_path = filename.clone().into_os_string();
-    output_path.push(".d");
+    Ok(())
+}
+
+pub fn output_depinfo<'a, 'b>(context: &mut Context<'a, 'b>, unit: &Unit<'a>) -> CargoResult<()> {
+    let mut deps = HashSet::new();
+    let mut visited = HashSet::new();
+    add_deps_for_unit(&mut deps, context, unit, &mut visited)?;
     let basedir = None; // TODO
-    let target_fn = render_filename(filename, basedir)?;
-    let mut outfile = File::create(output_path)?;
-    write!(outfile, "{}:", target_fn)?;
-    for dep in &deps {
-        write!(outfile, " {}", render_filename(dep, basedir)?)?;
+    for (_filename, link_dst, _linkable) in context.target_filenames(unit)? {
+        if let Some(link_dst) = link_dst {
+            let output_path = link_dst.with_extension("d");
+            let target_fn = render_filename(link_dst, basedir)?;
+            let mut outfile = File::create(output_path)?;
+            write!(outfile, "{}:", target_fn)?;
+            for dep in &deps {
+                write!(outfile, " {}", render_filename(dep, basedir)?)?;
+            }
+            writeln!(outfile, "")?;
+        }
     }
-    writeln!(outfile, "")?;
     Ok(())
 }